package tt.dz.egobus.servicemanager.service.impl;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import tt.dz.egobus.cache.service.ExtendCacheService;
import tt.dz.egobus.cache.service.impl.ExtendsRedisServiceImpl;
import tt.dz.egobus.servicemanager.core.lock.AbstractRedisCacheLock;
import tt.dz.egobus.servicemanager.core.task.DynamicTask;
import tt.dz.egobus.servicemanager.core.task.DynamicTaskNamespace;
import tt.dz.egobus.servicemanager.service.DynamicTaskService;

import java.util.*;

/**
 * @author Anson
 * @date 17-8-4
 * @name 根据redis获取当前存活的动态任务
 * @since 1.0.6
 */
@Service("redisDynamicTaskService")
public class RedisDynamicTaskService extends ExtendsRedisServiceImpl implements DynamicTaskService {

    private static final String REDIS_DYNAMIC_TASK_CACHE_KEY = "EGOBUS_DYNAMIC_TASK_CACHE_KEY";
    private static final String REDIS_DYNAMIC_TASK_CACHE_LOCK_KEY = "EGOBUS_DYNAMIC_TASK_CACHE_LOCK_KEY";

    /**
     * @author Anson
     * @date 17-8-7
     * @name 当前redis缓存锁
     * @since 1.0.6
     */
    protected class RedisDynamicTaskServiceLock extends AbstractRedisCacheLock {
        @Override
        protected ExtendCacheService cacheService() {
            return RedisDynamicTaskService.this;
        }

        @Override
        protected String getLockKey() {
            return REDIS_DYNAMIC_TASK_CACHE_LOCK_KEY;
        }
    }

    @Override
    public List<DynamicTask> getCurLiveDynamicTask() {
        Jedis jedis = this.getJedis();
        try {
            Map<String, DynamicTask> taskMap = this.getRedisDynamicTaskCacheMap(jedis);
            if (taskMap == null) {
                return Collections.emptyList();
            }
            return new ArrayList<DynamicTask>(taskMap.values());
        } finally {
            jedis.close();
        }
    }

    @Override
    public void addDynamicTask(DynamicTask... tasks) {
        if (tasks == null || tasks.length == 0) {
            return;
        }
        Jedis jedis = this.getJedis();
        String bKey = this.getRedisDynamicTaskCacheKey();
        RedisDynamicTaskServiceLock cacheLock = new RedisDynamicTaskServiceLock();
        if (cacheLock.aquireLock()) {
            try {
                for (DynamicTask task : tasks) {
                    if (this.isContainerDynamicTaskKey(jedis, task)) {
                        continue;
                    }
                    jedis.rpush(bKey, task.toJsonStr());
                }
            } finally {
                jedis.close();
                cacheLock.unlock();
            }
        }
    }

    @Override
    public boolean isContainerDynamicTask(DynamicTask task) {
        if (task == null || StringUtils.isBlank(task.key())) {
            return false;
        }
        Jedis jedis = this.getJedis();
        try {
            return this.isContainerDynamicTaskKey(jedis, task);
        } finally {
            jedis.close();
        }
    }

    @Override
    public void deleteDynamicTask(DynamicTask task) {
        if (task == null || StringUtils.isBlank(task.key())) {
            return;
        }
        this.deleteDynamicTaskNamespace(task);
    }

    @Override
    public void deleteDynamicTaskNamespace(DynamicTaskNamespace taskNamespace) {
        Jedis jedis = this.getJedis();
        String key = this.getRedisDynamicTaskCacheKey();
        List<DynamicTask> tasks = getAllCacheTask(jedis);
        RedisDynamicTaskServiceLock cacheLock = new RedisDynamicTaskServiceLock();
        if (CollectionUtils.isEmpty(tasks)) {
            return;
        }
        if (cacheLock.aquireLock()) {
            try {
                Iterator<DynamicTask> iterator = tasks.iterator();
                DynamicTask t = null;
                while (iterator.hasNext()) {
                    t = iterator.next();
                    if (taskNamespace.key().equals(t.key())) {
                        iterator.remove();
                        break;
                    }
                }
                List<String> taskJsons = DynamicTask.convertTaskJson(tasks);
                String[] values = new String[taskJsons.size()];
                values = taskJsons.toArray(values);
                jedis.del(key);
                if (taskJsons != null && !taskJsons.isEmpty()) {
                    jedis.lpush(key, values);
                }
            } finally {
                jedis.close();
                cacheLock.unlock();
            }
        }
    }

    @Override
    public Map<String, DynamicTask> getCurLiveDynamicMapTask() {
        Jedis jedis = this.getJedis();
        try {
            return this.getRedisDynamicTaskCacheMap(jedis);
        } finally {
            jedis.close();
        }
    }


    @Override
    public void modifyDynamicTask(DynamicTask task) {
        if (task == null) {
            return;
        }
        Jedis jedis = this.getJedis();
        String bKey = this.getRedisDynamicTaskCacheKey();
        RedisDynamicTaskServiceLock cacheLock = new RedisDynamicTaskServiceLock();
        if (cacheLock.aquireLock()) {
            try {
                this.deleteDynamicTask(task);
                jedis.rpushx(bKey, task.toJsonStr());
            } finally {
                jedis.close();
                cacheLock.unlock();
            }
        }
    }

    public String getRedisDynamicTaskCacheKey() {
        return REDIS_DYNAMIC_TASK_CACHE_KEY;
    }

    protected boolean isContainerDynamicTaskKey(final Jedis jedis, DynamicTask task) {
        if (task == null || StringUtils.isBlank(task.key())) {
            return false;
        }
        Map<String, DynamicTask> dynamicTasks = this.getRedisDynamicTaskCacheMap(jedis);
        return dynamicTasks.containsKey(task.key());
    }

    /**
     * @param jedis 当前jedis
     * @author Anson
     * @date 17-8-4
     * @name 获取当前缓存
     * 调用者释放当前redis链接
     * @since 1.0.6
     */
    protected Map<String, DynamicTask> getRedisDynamicTaskCacheMap(final Jedis jedis) {
        List<DynamicTask> dynamicTasks = this.getAllCacheTask(jedis);
        return DynamicTask.dynamicTaskListToMap(dynamicTasks);
    }

    protected List<DynamicTask> getAllCacheTask(final Jedis jedis) {
        String bKey = this.getRedisDynamicTaskCacheKey();
        if (jedis == null || !getJedis().exists(bKey)) {
            return null;
        }
        return DynamicTask.convertTask(this.getAllCacheTaskStrs(jedis));
    }

    protected List<String> getAllCacheTaskStrs(final Jedis jedis) {
        String bKey = this.getRedisDynamicTaskCacheKey();
        if (getJedis() == null || !getJedis().exists(bKey)) {
            return null;
        }
        List<String> dynamicTaskStrs = jedis.lrange(bKey, 0, -1);
        return dynamicTaskStrs;
    }

}
